﻿#define _CRT_SECURE_NO_WARNINGS
//使用回调函数改造前
//#include <stdio.h>
//int add(int a, int b)
//{
//	return a + b;
//}
//int sub(int a, int b)
//{
//	return a - b;
//}
//int mul(int a, int b)
//{
//	return a * b;
//}
//int div(int a, int b)
//{
//	return a / b;
//}
//int main()
//{
//	int x, y;
//	int input = 1;
//	int ret = 0;
//	do
//	{
//		printf("*************************\n");
//		printf("	  1:add 2:sub \n");
//		printf("	  3:mul 4:div \n");
//		printf("*************************\n");
//		printf("请选择：");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1:
//			printf("输入操作数：");
//			scanf("%d %d", &x,&y);
//			ret = add(x, y);
//			printf("ret = %d\n",ret);
//			break;
//		case 2:
//			printf("输入操作数：");
//			scanf("%d %d", &x,&y);
//			ret = sub(x, y);
//			printf("ret = %d\n",ret);
//			break;
//		case 3:
//			printf("输入操作数：");
//			scanf("%d %d", &x,&y);
//			ret = mul(x, y);
//			printf("ret = %d\n",ret);
//			break;
//		case 4:
//			printf("输入操作数：");
//			scanf("%d %d", &x,&y);
//			ret = div(x, y);
//			printf("ret = %d\n",ret);
//			break;
//		case 0:
//			printf("退出程序\n");
//			break;
//		default:
//			printf("选择错误\n");
//			break;
//		}
//	} while (input);
//	return 0;
//}

////使用回到函数改造后
//#include <stdio.h>
//int add(int a, int b)
//{
//	return a + b;
//}
//int sub(int a, int b)
//{
//	return a - b;
//}
//int mul(int a, int b)
//{
//	return a * b;
//}
//int div(int a, int b)
//{
//	return a / b;
//}
//void calc(int(*pf)(int, int))
//{
//	int ret = 0;
//	int x, y;
//	printf("输入操作数：");
//	scanf("%d %d", &x, &y);
//	ret = pf(x, y);
//	printf("ret = %d\n", ret);
//}
//int main()
//{
//	int input = 1;
//	do
//	{
//		printf("*************************\n");
//		printf("	1:add 2:sub \n");
//		printf("	3:mul 4:div \n");
//		printf("*************************\n");
//		printf("请选择：");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1:
//			calc(add);
//			break;
//		case 2:
//			calc(sub);
//			break;
//		case 3:
//			calc(mul);
//			break;
//		case 4:
//			calc(div);
//			break;
//		case 0: printf("退出程序\n");
//			break;
//		default:
//			printf("选择错误\n");
//			break;
//		}
//	} while (input);
//	return 0;
//}

//void qsort(void* base, size_t num, size_t size,
//    int (*compar)(const void*, const void*));


//int int_cmp(const void* p1, const void* p2)
//{
//	return *(int*)p1 - *(int*)p2;//这个代码首先对 p1 和 p2 进行了强制类型转换，然后解引用
//}
//
//int int_cmp(const void* p1, const void* p2)
//{
//	if (*(int*)p1 > *(int*)p2)
//		return 1;
//	else if (*(int*)p1 < *(int*)p2)
//		return -1;
//	else
//		return 0;
//}
//
//int int_cmp(const void* p1, const void* p2)
//{
//	return *(int*)p2 - *(int*)p1;//这里 p1 和 p2 调换了位置
//}
//
//
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9 };		 //注意，qsort 排序的结果默认是升序的，
//	size_t sz = sizeof(arr) / sizeof(arr[0]);//所以我们先用一个降序的数组做测试
//
//	qsort(arr, sz, sizeof(arr[0]), int_cmp);//使用 qsort 进行排序
//	//这里的 sz 就是数据的个数， sizeof(arr[0]) 就是每个数据的大小
//	for (int i = 0; i < sz;i++)//打印一下
//		printf("%d ", arr[i]);
//	printf("\n");
//	return 0;
//}

//#include<stdio.h>
//#include<stdlib.h>//注意 qsort 函数包含在这个头文件中
//#include<string.h>// strcmp 包含在这个头文件中
//typedef struct stu
//{
//	char name[10];
//	int age;
//}stu;//想一想，stu 结构体中有两个成员，我们要用哪一个来排序呢？
//
//int age_cmp(const void* p1, const void* p2)
//{	//按年龄排序
//	return ((stu*)p1)->age - ((stu*)p2)->age;
//}
//
//int name_cmp(const void* p1, const void* p2)
//{	//按名字排序
//	return strcmp(((stu*)p1)->name, ((stu*)p1)->name);
//}	//strcmp 是一个库函数，我们在后面介绍
//
//void Print(stu* s,size_t sz)
//{	//这个函数用来打印结构体，方便我们观察
//	static int time = 1;
//	printf("第%d次\n", time++);
//	for (int i = 0; i < sz; i++)
//	{
//		printf("%s %d\n", s[i].name, s[i].age);
//	}
//}
//
//int main()
//{
//	stu s[] = { {"zhangsan", 15}, {"lisi", 30}, {"wangwu", 20} };//创建一个 stu 数组并初始化
//	size_t sz = sizeof(s) / sizeof(s[0]);
//	Print(s, sz);
//
//	qsort(s, sz, sizeof(s[0]), age_cmp);//先根据年龄排序一下
//	Print(s, sz);
//
//	qsort(s, sz, sizeof(s[0]), name_cmp);//再根据名字排序一下
//	Print(s, sz);
//
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int a = 10;
//	printf("%d\n", sizeof(a));
//	printf("%d\n", sizeof a);
//	printf("%d\n", sizeof(int));
//
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	char arr1[3] = { 'a', 'b', 'c' };//arr1 后面没有 \0
//	char arr2[] = "abc";			 //arr2 后面有 \0
//	printf("%d\n", strlen(arr1));//随机
//	printf("%d\n", strlen(arr2));//3
//
//	printf("%d\n", sizeof(arr1));//3
//	printf("%d\n", sizeof(arr2));//4
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	int a[] = { 1,2,3,4 };
//	printf("%zd\n", sizeof(a));		//这里 a 代表数组					16
//	printf("%zd\n", sizeof(a + 0));	// a+0 是一个指针,指向数组首元素	8
//	printf("%zd\n", sizeof(*a));	//解引用 a 得到数组首元素			4
//	printf("%zd\n", sizeof(a + 1)); // a+0 是一个指针,指向数组第二个元素8
//	printf("%zd\n", sizeof(a[1]));  //数组的第二个元素					4
//	printf("%zd\n", sizeof(&a));	//数组的地址，也是一个指针			8
//	printf("%zd\n", sizeof(*&a));   //数组的地址解引用，得到数组		16
//	printf("%zd\n", sizeof(&a + 1));//跳过整个数组，但还是一个指针		8
//	printf("%zd\n", sizeof(&a[0])); //取出第一个元素的地址，是一个指针	8
//	printf("%zd\n", sizeof(&a[0] + 1));//第二个元素的地址，指针			8
//	return 0;
//}
//#include<stdio.h>
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };//注意后面没有 \0
//	printf("%zd\n", sizeof(arr));		//数组大小					6
//	printf("%zd\n", sizeof(arr + 0));	//指向第一个元素的指针		8
//	printf("%zd\n", sizeof(*arr));		//第一个元素的大小			1
//	printf("%zd\n", sizeof(arr[1]));		//第一个元素的大小			1
//	printf("%zd\n", sizeof(&arr));		//指向整个数组的指针		8
//	printf("%zd\n", sizeof(&arr + 1));	//跳过整个数组，但还是指针	8
//	printf("%zd\n", sizeof(&arr[0] + 1));//指向第二个元素的指针		8
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%d\n", strlen(arr));		//从 arr 向后找 \0，字符串中没有	随机值
//	printf("%d\n", strlen(arr + 0));	//从 arr 向后找 \0，字符串中没有	随机值
//	printf("%d\n", strlen(*arr));		//传递给 strlen 一个字符			报错
//	printf("%d\n", strlen(arr[1]));		//传递给 strlen 一个字符			报错
//	printf("%d\n", strlen(&arr));		//从 arr 向后找 \0，字符串中没有	随机值
//	printf("%d\n", strlen(&arr + 1));	//跳过整个数组后开始找 \0			随机值
//	printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始找 \0				随机值
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	char arr[] = "abcdef";//后面有 \0
//	printf("%zd\n", sizeof(arr));		//整个数组的大小			7
//	printf("%zd\n", sizeof(arr + 0));	//指向第一个元素的指针		8
//	printf("%zd\n", sizeof(*arr));		//第一个元素的大小			1
//	printf("%zd\n", sizeof(arr[1]));	//第一个元素的大小			1
//	printf("%zd\n", sizeof(&arr));		//指向整个数组的指针		8
//	printf("%zd\n", sizeof(&arr + 1));	//跳过整个数组，还是指针	8
//	printf("%zd\n", sizeof(&arr[0] + 1));//指向第二个元素的指针		8
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	char arr[] = "abcdef";//后面有 \0
//	printf("%d\n", strlen(arr));		//从 arr 开始找 \0			6
//	printf("%d\n", strlen(arr + 0));	//从 arr 开始找 \0			6
//	printf("%d\n", strlen(*arr));		//传递给 strlen 一个字符	报错
//	printf("%d\n", strlen(arr[1]));		//传递给 strlen 一个字符	报错
//	printf("%d\n", strlen(&arr));		//从 arr 开始找 \0			6
//	printf("%d\n", strlen(&arr + 1));	//跳过整个数组开始找 \0		随机值
//	printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始找 \0		5
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	char* p = "abcdef";//字符串常量，有 \0
//	printf("%zd\n", sizeof(p));			//指针变量				8
//	printf("%zd\n", sizeof(p + 1));		//指向第二个元素的指针	8
//	printf("%zd\n", sizeof(*p));		//第一个元素			1
//	printf("%zd\n", sizeof(p[0]));		//第一个元素			1
//	printf("%zd\n", sizeof(&p));		//数组的地址，指针		8
//	printf("%zd\n", sizeof(&p + 1));	//跳过整个数组，指针	8
//	printf("%zd\n", sizeof(&p[0] + 1));	//指向第二个元素的指针	8
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	char* p = "abcdef";
//	printf("%d\n", strlen(p));			//6
//	printf("%d\n", strlen(p + 1));		//5
//	printf("%d\n", strlen(*p));			//报错		
//	printf("%d\n", strlen(p[0]));		//报错
//	printf("%d\n", strlen(&p));			//6
//	printf("%d\n", strlen(&p + 1));		//随机值
//	printf("%d\n", strlen(&p[0] + 1));	//5
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));			
//	//整个二维数组的大小，48
//	printf("%zd\n", sizeof(a[0][0]));
//	//第一行第一个的元素的大小，4
//	printf("%zd\n", sizeof(a[0]));
//	//第一行元素的大小，a[0]相当于第一行的数组名，16
//	printf("%zd\n", sizeof(a[0] + 1));
//	//指向第一行元素第二个元素的指针，8
//	printf("%zd\n", sizeof(*(a[0] + 1)));
//	//第一行第二个元素的大小，4
//	printf("%zd\n", sizeof(a + 1));
//	//跳过整个数组，指针变量，8
//	printf("%zd\n", sizeof(*(a + 1)));
//	//跳过第一行，只想第二行的指针变量，相当于数组名，16
//	printf("%zd\n", sizeof(&a[0] + 1));
//	//跳过第一行，指向第二行的指针变量，8
//	printf("%zd\n", sizeof(*(&a[0] + 1)));
//	//第二行所有元素的大小，16
//	printf("%zd\n", sizeof(*a));
//	//指向第一行的数组，相当于数组名，16
//	printf("%zd\n", sizeof(a[3]));
//	//越界访问，但类型为 int(*)[4]，为指针变量，且相当于数组名，16
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };
//	int* ptr = (int*)(&a + 1);
//	printf("%d,%d", *(a + 1), *(ptr - 1));
//	return 0;
//}
////程序的结果是什么？

//在X86环境下
//假设结构体的大小是20个字节（为什么是 20 将在之后的博客中解释）
//程序输出的结果是啥？
//#include<stdio.h>
//struct Test
//{
//	int Num;
//	char* pcName;
//	short sDate;
//	char cha[2];
//	short sBa[4];
//}*p = (struct Test*)0x100000;
//
//int main()
//{
//	printf("%p\n", p + 0x1);
//	printf("%p\n", (unsigned long)p + 0x1);
//	printf("%p\n", (unsigned int*)p + 0x1);
//	return 0;
//}